<template>
  <div>
    <!-- 新增todo -->
    <input
      type="text"
      v-model="newTodo"
      @keyup.enter="addTodo"
      autofocus
      placeholder="新增今日待办"
      autocomplete="off"
    />

    <!-- todo 列表 -->
    <ul>
      <li
        v-for="todo in filtersTodos"
        :key="todo.id"
        :class="{ complated: todo.complated, editing: todo === editedTodo }"
      >
        <!-- 绑定完成状态 -->
        <div class="view">
          <input type="checkbox" v-model="todo.complated" />
          <label @dblclick="editTodo(todo)">{{ todo.title }}</label>
          <button @click="removeTodo">×</button>
        </div>
        <!-- 编辑待办 -->
        <input
          type="text"
          class="edit"
          v-model="todo.title"
          v-todo-focus="todo === editedTodo"
          @blur="doneEdit(todo)"
          @keyup.enter="doneEdit(todo)"
          @keyup.escape="cancelEdit(todo)"
        />
      </li>
    </ul>

    <!-- 过滤 -->
    <p class="filters">
      <span
        @click="visibility = 'all'"
        :class="{ selected: visibility === 'all' }"
        >All</span
      >
      <span
        @click="visibility = 'active'"
        :class="{ selected: visibility === 'active' }"
        >Active</span
      >
      <span
        @click="visibility = 'completed'"
        :class="{ selected: visibility === 'completed' }"
        >Completed</span
      >
    </p>
  </div>
</template>

<script>
import { reactive, toRefs, computed, watchEffect } from "vue";

const filters = {
  all(todos) {
    return todos;
  },
  active(todos) {
    return todos.filter((todo) => !todo.complated);
  },
  completed(todos) {
    return todos.filter((todo) => todo.complated);
  },
};

// 缓存操作
const todoStorage = {
  fetch() {
    let todos = JSON.parse(localStorage.getItem("vue3-todos") || "[]");
    todos.forEach((todo, index) => (todo.id = index + 1));
    return todos;
  },
  save(todos) {
    localStorage.setItem("vue3-todos", JSON.stringify(todos));
  },
};

export default {
  setup() {
    const state = reactive({
      newTodo: "",
      todos: todoStorage.fetch(),
      beforeEditCache: "",
      editedTodo: null, // 正在编辑的todo
      visibility: "all",
      filtersTodos: computed(() => {
        return filters[state.visibility](state.todos);
      }),
    });

    function addTodo() {
      state.todos.push({
        id: state.todos.length + 1,
        title: state.newTodo,
        complated: false,
      });
      state.newTodo = "";
    }

    function removeTodo(todo) {
      state.todos.splice(state.todos.indexOf(todo), 1);
    }

    function editTodo(todo) {
      state.beforeEditCache = todo.title;
      state.editedTodo = todo;
    }

    function cancelEdit(todo) {
      todo.title = state.beforeEditCache;
      state.editedTodo = null;
    }

    function doneEdit(todo) {
      state.editedTodo = null;
    }

    watchEffect(() => {
      todoStorage.save(state.todos);
    });

    return {
      ...toRefs(state),
      addTodo,
      removeTodo,
      editTodo,
      cancelEdit,
      doneEdit,
    };
  },
  directives: {
    "todo-focus": (el, { value }) => {
      if (value) {
        el.focus();
      }
    },
  },
};
</script>

<style scoped>
.complated label {
  text-decoration: line-through;
}

.edit,
.editing .view {
  display: none;
}

.view,
.editing .edit {
  display: block;
}

.filters > span {
  padding: 2px 4px;
  margin-right: 4px;
  border: 1px solid transparent;
}

.filters > span.selected {
  border-color: rgba(173, 47, 471, 0.2);
}
</style>
